﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Microsoft.AspNetCore.Mvc;
using shenghua.Authorization;
using shenghua.Common.Dto;
using shenghua.Member.Members.Dto;
using shenghua.Member.XP;

namespace shenghua.Member.Members
{
    public class MemberAppService: shenghuaAppServiceBase, IMemberAppService
    {
        private readonly MemberManager _memberManager;
        private readonly IRepository<Member, long> _memberRepository;
        private readonly XPManager _xpManager;
        private readonly IRepository<XPLog> _xpLogRepository;

        public MemberAppService(
            MemberManager memberManager,
            IRepository<Member, long> memberRepository,
            XPManager xpManager,
            IRepository<XPLog> xpLogRepository
            )
        {
            _memberManager = memberManager;
            _memberRepository = memberRepository;
            _xpManager = xpManager;
            _xpLogRepository = xpLogRepository;
        }

        public async Task<MemberDto> Register(CreateMemberDto input)
        {
            var member =
                await _memberManager.Create(
                    input.UserName,
                    input.Password,
                    input.Name,
                    input.PhoneNumber,
                    input.EmailAddress);
            
            return ObjectMapper.Map<MemberDto>(member);
        }

        [AbpAuthorize(PermissionNames.MemberManagement)]
        public async Task<MemberDto> Get(EntityDto<long> input)
        {
            Member member = await _memberManager.Get(input.Id);
            return ObjectMapper.Map<MemberDto>(member);
        }

        [AbpAuthorize(PermissionNames.Member)]
        public async Task<MemberDto> GetSelf()
        {
            Member member = await _memberManager.Get((int)AbpSession.UserId);
            return ObjectMapper.Map<MemberDto>(member);
        }

        [AbpAuthorize(PermissionNames.MemberManagement)]
        public async Task<MemberDto> Create(CreateMemberDto input)
        {
            Member member = Member.CreateMember(input.UserName, input.Name, input.PhoneNumber, input.EmailAddress);
            input.MapTo(member);

            await _memberManager.Create(member, input.Password);
            return new MemberDto(member);
        }

        [AbpAuthorize(PermissionNames.MemberManagement)]
        public async Task<MemberDto> Update(UpdateMemberDto input)
        {
            Member member = await _memberManager.Get(input.Id);
            input.MapTo(member);

            if(input.ResetPassword)
            {
                await _memberManager.Update(member, input.Password);
            }
            else
            {
                await _memberManager.Update(member);
            }
            return new MemberDto(member);
        }

        [AbpAuthorize(PermissionNames.MemberManagement)]
        [HttpPost]
        public async Task Delete(BatchlongIdDto input)
        {
            foreach(long id in input.Ids)
            {
                await _memberManager.Delete(id);
            }
        }

        [AbpAuthorize(PermissionNames.Member)]
        public async Task UpdatePersonalProfile(UpdatePersonalProfileDto input)
        {
            var member = await GetCurrentMemberAsync();
            member.Head = input.Head;
            member.Name = input.Name;
            member.Sex = input.Sex;
            member.SetFormItems(input.FormItems);
        }
        
        [AbpAuthorize(PermissionNames.MemberManagement)]
        public async Task<SearchResultDto<MemberDto>> Search(SearchMemberDto input)
        {
            var query = _memberRepository.GetAll();

            if (!string.IsNullOrWhiteSpace(input.Search))
            {
                switch (input.SearchTarget)
                {
                    case "username": query = query.Where(r => r.UserName.Contains(input.Search)); break;
                    case "name": query = query.Where(r => r.Name.Contains(input.Search)); break;
                    case "phonenumber": query = query.Where(r => r.PhoneNumber.Contains(input.Search)); break;
                    case "emailaddress": query = query.Where(r => r.EmailAddress.Contains(input.Search)); break;
                }
            }

            int totalCount = query.Count();
            List<Member> members = query.ToList();
            return new SearchResultDto<MemberDto>
            {
                TotalCount = totalCount,
                Items = ObjectMapper.Map<List<MemberDto>>(members)
            };
        }

        [AbpAuthorize(PermissionNames.Member)]
        [HttpPost]
        public async Task<PagedResultDto<XPLogDto>> GetAllXPLogs(SearchDto input)
        {
            var query = _xpLogRepository.GetAll().Where(r => r.MemberId == MemberId);
            int totalCount = query.Count();
            var items = query.OrderByDescending(r => r.CreationTime).Skip(input.SkipCount).Take(input.MaxResultCount).ToList();
            return new PagedResultDto<XPLogDto>
            {
                TotalCount = totalCount,
                Items = ObjectMapper.Map<List<XPLogDto>>(items)
            };
        }

        [HttpPost]
        public async Task<List<MemberMiniProfileDto>> GetProfiles(BatchlongIdDto input)
        {
            var items = _memberRepository.GetAll().Where(r => input.Ids.Contains(r.Id)).ToList();
            return ObjectMapper.Map<List<MemberMiniProfileDto>>(items);
        }

        [AbpAuthorize(PermissionNames.Member)]
        public async Task ChangePassword(ChangePasswordDto input)
        {
            var member = await GetCurrentMemberAsync();
            await _memberManager.ChangePassword(member, input.currentPassword, input.newPassword);
        }
    }
}
